﻿

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using NetCore.Ado;
using NetCore.WF.BLL.Domain;
using NetCore.WF.Model;
namespace NetCore.WF.BLL
{
    public partial class FlowService
    {
        public const string Cache_Flow_Service_FlowDesigner = "Cache_Flow_Service_FlowDesigner_";
        public const string Cache_Flow_Service_V_FlowDesigner = "Cache_Flow_Service_V_FlowDesigner_";
        private static readonly object locked = new object();
        public string LogPath
        {
            get
            {
                return RootPath + "/log/";
            }
        }
        public string CheckoutPath
        {
            get
            {
                return RootPath + "/checkout/";
            }
        }

        public List<FlowDesigner> GetTempAllFlow()
        {
            List<FlowDesigner> entities = new List<FlowDesigner>();
            lock (locked)
            {

                DirectoryInfo directoryInfo = new DirectoryInfo(this.CheckoutPath);
                if (!directoryInfo.Exists)
                {
                    return null;
                }
                FileInfo[] files = directoryInfo.GetFiles();
                foreach (var file in files)
                {
                    var entity = ReadFlowDesigner(file.FullName);
                    if (entity != null)
                    {
                        entities.Add(entity);
                    }
                }
            }
            return entities;
        }

        public FlowDesigner ReadFlowDesigner(string path)
        {
            lock (locked)
            {
                string flowData = FileHelper.ReadLine(path);
                if (!string.IsNullOrWhiteSpace(flowData))
                {
                    var entity = JSONHelper.FromJson<FlowDesigner>(flowData);
                    return entity;
                }
            }
            return null;
        }

        public FlowDesigner GetFlowById(string id, int version = 0)
        {
            if (version > 0)
            {
              return  CacheService.GetOrCreate<FlowDesigner>(Cache_Flow_Service_V_FlowDesigner+ id+"_"+version.ToString(), ()=> {
                    var versionEntity = this.Select<FlowVersionEntity>(Expression.And(Expression.Eq(FlowVersionEntity.__FlowId, id), Expression.Eq(FlowVersionEntity.__Version, version)));
                    if (versionEntity != null)
                    {
                        var designer = JSONHelper.FromJson<FlowDesigner>(versionEntity.Chart);
                      designer.Flow.FlowId = versionEntity.FlowVersionId;
                        if (versionEntity != null)
                        {
                            designer.Flow = this.GetById(id);
                        }
                      designer.Flow.IsCheckOut = false;
                      designer.Flow.CheckOutUserId = "";
                      designer.Flow.IsEdited = false;
                      return designer;
                    }
                    return null;
                },true);
               

            }
            FlowDesigner entity = ReadFlowDesigner(this.CheckoutPath + id + ".json");
            if (entity == null)
            {
                entity = new FlowDesigner();
                var flow = this.GetById(id);
                if (flow != null && !string.IsNullOrWhiteSpace(flow.Chart))
                {
                    entity = JSONHelper.FromJson<FlowDesigner>(flow.Chart);
                    if (entity != null)
                    {
                        entity.Flow = flow;
                        if (entity.Flow.IsCheckOut && entity.Flow.CheckOutUserId.Equals(ApplicationEnvironments.DefaultSession.UserId))
                        {
                            string strError = "";
                            this.SaveFile(entity, ref strError);
                        }
                    }
                }
                if (entity == null)
                {
                    entity = new FlowDesigner();
                }
                entity.Flow = flow;
            }
            if (entity != null && entity.Flow != null)
            {
                entity.Flow.IsEdited = entity.Flow.IsCheckOut && entity.Flow.CheckOutUserId.Equals(ApplicationEnvironments.DefaultSession.UserId);
            }
            return entity;
        }

        /// <summary>
        /// 保存流程图
        /// </summary>
        /// <param name="flowDesigner"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool SaveWorkflow(FlowDesigner flowDesigner, ref string strError)
        {
            if (Exist(flowDesigner.Flow.FlowName, flowDesigner.Flow.FlowId))
            {
                strError = flowDesigner.Flow.FlowName + "已存在，请不要重复输入";
                return false;
            }
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            keyValuePairs.Add("FlowType", flowDesigner.Flow.FlowTypeId);
            var designer = this.GetFlowById(flowDesigner.Flow.FlowId);
            if (designer == null)
            {
                designer = flowDesigner;
                if (string.IsNullOrWhiteSpace(designer.Flow.FlowId))
                {
                    designer.Flow.IsNewAdd = true;
                    designer.Flow.FlowId = Guid.NewGuid().ToString();
                }
            }
            else
            {
                designer.states = flowDesigner.states;
                designer.paths = flowDesigner.paths;
                designer.Flow = flowDesigner.Flow;
            }
            return this.SaveFile(designer, ref strError);
        }

        /// <summary>
        /// 执行保存动作，存储物理文件以及更新缓存
        /// </summary>
        /// <param name="flowDesigner"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool SaveFile(FlowDesigner flowDesigner, ref string strError)
        {
            lock (locked)
            {
                if (!flowDesigner.Flow.IsCheckOut || !flowDesigner.Flow.CheckOutUserId.Equals(ApplicationEnvironments.DefaultSession.UserId))
                {
                    strError = "流程尚未迁出，无法修改";
                    return false;
                }
                lock (locked)
                {
                    string filePath = this.CheckoutPath + flowDesigner.Flow.FlowId + ".json";
                    FileInfo fileInfo = new FileInfo(filePath);
                    if (!fileInfo.Exists)
                    {
                        if (!fileInfo.Directory.Exists)
                        {
                            fileInfo.Directory.Create();
                        }
                    }
                    FileHelper.WriteLine(filePath, flowDesigner.ToJson());
                }
            }
            return true;
        }

        /// <summary>
        /// 保存流程基本信息
        /// </summary>
        /// <param name="flowEntity">流程实体</param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool SaveFlow(FlowEntity flowEntity, ref string strError)
        {
            if (Exist(flowEntity.FlowName, flowEntity.FlowId))
            {
                strError = flowEntity.FlowName + "已存在，请不要重复输入";
                return false;
            }
            if (string.IsNullOrWhiteSpace(flowEntity.FlowId))
            {
                Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
                keyValuePairs.Add("FlowType", flowEntity.FlowTypeId);
                flowEntity.FlowId = new NetCore.BLL.SerialRuleService().CreateSerialNo(Flow_Identity_Num, keyValuePairs, ref strError);// 主键生成值
                flowEntity.IsNewAdd = true;
                flowEntity.IsCheckOut = true;
                flowEntity.CheckOutUserId = ApplicationEnvironments.DefaultSession.UserId;
            }
            FlowDesigner flowDesigner = this.GetFlowById(flowEntity.FlowId);
            if (flowDesigner == null)
            {
                flowDesigner = new FlowDesigner();
            }
            var FlowEntities = this.GetTempAllFlow();
            var exist = FlowEntities.Where(x => x.Flow.FlowName.Equals(flowEntity.FlowName) && x.Flow.FlowId != flowEntity.FlowId).FirstOrDefault();
            if (exist != null)
            {
                strError = flowEntity.FlowName + "流程已存在";
                return false;
            }
            if (!string.IsNullOrWhiteSpace(flowEntity.ServiceClass))
            {
               var instance=  ReflectionHelper.Create(flowEntity.ServiceClass);
                if (instance != null)
                {
                    if (instance is IFlowEventListener)
                    {

                    }
                    else
                    {
                        strError = "该程序集中未实现IFlowEventListener接口";
                        return false;
                    }
                }
                else {
                    strError = "该程序集中未实现IFlowEventListener接口";
                    return false;
                }
            }
           
            flowDesigner.Flow = flowEntity;
            return this.SaveFile(flowDesigner, ref strError);
        }

        /// <summary>
        /// 保存参数
        /// </summary>
        /// <param name="flowParamsEntity">参数实体</param>
        /// <param name="strError">错误</param>
        /// <returns></returns>
        public bool SaveParams(FlowParamsEntity flowParamsEntity, ref string strError)
        {
            if (flowParamsEntity == null)
            {
                strError = "参数错误！";
                return false;
            }

            FlowDesigner flowDesigner = this.GetFlowById(flowParamsEntity.FlowId);
            if (flowDesigner == null)
            {
                strError = "参数错误！";
                return false;
            }
            if (flowDesigner.flowParams == null)
            {
                flowDesigner.flowParams = new Dictionary<string, FlowParamsEntity>();
            }
            if (string.IsNullOrWhiteSpace(flowParamsEntity.FlowParamId))
            {
                flowParamsEntity.FlowParamId = flowParamsEntity.FlowId+flowDesigner.flowMax.FlowParamNum++.ToString().PadLeft(3,'0');
            }
            var exist = flowDesigner.flowParams.Where(x => !x.Value.IsDeleted && x.Value.FlowParamName.Equals(flowParamsEntity.FlowParamName) && x.Key != flowParamsEntity.id).FirstOrDefault();
            if (!string.IsNullOrWhiteSpace(exist.Key))
            {
                strError = flowParamsEntity.FlowParamName + "已存在流程或者节点当中！";
                return false;
            }
            if (flowDesigner.flowParams.ContainsKey(flowParamsEntity.id))
            {
                flowDesigner.flowParams[flowParamsEntity.id] = flowParamsEntity;
            }
            else
            {
                flowDesigner.flowParams.Add(flowParamsEntity.FlowParamId, flowParamsEntity);
            }
            return this.SaveFile(flowDesigner, ref strError);
        }

        /// <summary>
        /// 删除参数
        /// </summary>
        /// <param name="flowid">流程Id</param>
        /// <param name="paramId">参数id</param>
        /// <param name="strError">错误信息</param>
        /// <returns></returns>
        public bool DeleteParams(string flowid, string paramId, ref string strError)
        {
            if (string.IsNullOrWhiteSpace(flowid) || string.IsNullOrWhiteSpace(paramId))
            {
                strError = "参数错误！";
                return false;
            }

            FlowDesigner flowDesigner = this.GetFlowById(flowid);
            if (flowDesigner == null)
            {
                strError = "流程未找到，无法删除！";
                return false;
            }
            if (flowDesigner.flowParams == null)
            {
                return true;
            }
            if (flowDesigner.flowParams.ContainsKey(paramId))
            {
                //flowDesigner.flowParams[paramId].IsDeleted = true;
                flowDesigner.flowParams.Remove(paramId);
                return this.SaveFile(flowDesigner, ref strError);
            }

            return true;
        }

        public bool SaveActivity(ActivityEntity activityEntity, ref string strError)
        {
            if (activityEntity == null)
            {
                strError = "参数错误！";
                return false;
            }

            FlowDesigner flowDesigner = this.GetFlowById(activityEntity.FlowId);
            if (flowDesigner == null)
            {
                strError = "参数错误！";
                return false;
            }
            if (flowDesigner.activities == null)
            {
                flowDesigner.activities = new Dictionary<string, ActivityEntity>();
            }
            if (string.IsNullOrWhiteSpace(activityEntity.ActivityId))
            {
                activityEntity.ActivityId = activityEntity.FlowId + flowDesigner.activities.Count.ToString().PadLeft(3, '0');
                activityEntity.IsNewAdd = true;
            }
            var exist = flowDesigner.activities.Where(x => !x.Value.IsDeleted && x.Value.ActivityName.Equals(activityEntity.ActivityName) && x.Key != activityEntity.ActivityId).FirstOrDefault();
            if (!string.IsNullOrWhiteSpace(exist.Key))
            {
                strError = activityEntity.ActivityName + "已存在流程或者节点当中！";
                return false;
            }
            if (flowDesigner.activities.ContainsKey(activityEntity.ActivityId))
            {
                flowDesigner.activities[activityEntity.ActivityId] = activityEntity;
            }
            else
            {
                flowDesigner.activities.Add(activityEntity.ActivityId, activityEntity);
            }
            return this.SaveFile(flowDesigner, ref strError);
        }

        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="flowid"></param>
        /// <param name="activityId"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool DeleteActivity(string flowid, string activityId, ref string strError)
        {
            if (string.IsNullOrWhiteSpace(flowid) || string.IsNullOrWhiteSpace(activityId))
            {
                strError = "参数错误！";
                return false;
            }

            FlowDesigner flowDesigner = this.GetFlowById(flowid);
            if (flowDesigner == null)
            {
                strError = "流程未找到，无法删除！";
                return false;
            }
            if (flowDesigner.activities == null)
            {
                return true;
            }
            if (flowDesigner.activities.ContainsKey(activityId))
            {
               // flowDesigner.activities[activityId].IsDeleted = true;
                flowDesigner.activities.Remove(activityId);
                return this.SaveFile(flowDesigner, ref strError);
            }

            return true;
        }

        /// <summary>
        /// 保存规则
        /// </summary>
        /// <param name="flowRulesEntity"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool SaveRules(FlowRulesEntity flowRulesEntity, ref string strError)
        {
            if (flowRulesEntity == null)
            {
                strError = "参数错误！";
                return false;
            }

            FlowDesigner flowDesigner = this.GetFlowById(flowRulesEntity.FlowId);
            if (flowDesigner == null)
            {
                strError = "参数错误！";
                return false;
            }
            if (flowDesigner.flowRules == null)
            {
                flowDesigner.flowRules = new Dictionary<string, Dictionary<string, FlowRulesEntity>>();
            }
            if (string.IsNullOrWhiteSpace(flowRulesEntity.FlowRuleId))
            {
                flowRulesEntity.FlowRuleId = flowRulesEntity.FlowId + flowDesigner.flowMax.FlowRuleNum++.ToString().PadLeft(3, '0');
                flowRulesEntity.ToType = 0;
            }
            if (flowDesigner.flowRules.ContainsKey(flowRulesEntity.ActivityId))
            {
                Dictionary<string, FlowRulesEntity> activityRule = flowDesigner.flowRules[flowRulesEntity.ActivityId];
                if (activityRule != null)
                {
                    var exist = activityRule.Where(y => y.Value.FlowRuleName.Equals(flowRulesEntity.FlowRuleName) && y.Key != flowRulesEntity.FlowRuleId).FirstOrDefault();
                    if (!string.IsNullOrWhiteSpace(exist.Key))
                    {
                        strError = flowRulesEntity.FlowRuleName + "规则名称已存在！";
                        return false;
                    }
                }
            }
            if (flowDesigner.flowRules.ContainsKey(flowRulesEntity.ActivityId) && flowDesigner.flowRules[flowRulesEntity.ActivityId].ContainsKey(flowRulesEntity.FlowRuleId))
            {
                flowDesigner.flowRules[flowRulesEntity.ActivityId][flowRulesEntity.FlowRuleId] = flowRulesEntity;
            }
            else
            {
                if (!flowDesigner.flowRules.ContainsKey(flowRulesEntity.ActivityId))
                {
                    flowDesigner.flowRules[flowRulesEntity.ActivityId] = new Dictionary<string, FlowRulesEntity>();
                }
                flowDesigner.flowRules[flowRulesEntity.ActivityId].Add(flowRulesEntity.FlowRuleId, flowRulesEntity);
            }
            return this.SaveFile(flowDesigner, ref strError);
        }

        /// <summary>
        /// 删除规则
        /// </summary>
        /// <param name="flowid"></param>
        /// <param name="activityId"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool DeleteRule(string flowid, string activityId, string ruleid, ref string strError)
        {
            if (string.IsNullOrWhiteSpace(flowid) || string.IsNullOrWhiteSpace(activityId))
            {
                strError = "参数错误！";
                return false;
            }

            FlowDesigner flowDesigner = this.GetFlowById(flowid);
            if (flowDesigner == null)
            {
                strError = "流程未找到，无法删除！";
                return false;
            }
            if (flowDesigner.activities == null)
            {
                return true;
            }
            if (flowDesigner.flowRules.ContainsKey(activityId))
            {
                if (flowDesigner.flowRules[activityId] != null && flowDesigner.flowRules[activityId].ContainsKey(ruleid))
                {
                    flowDesigner.flowRules[activityId].Remove(ruleid);
                  // flowDesigner.flowRules[activityId][ruleid].IsDeleted = true;
                    this.SaveFile(flowDesigner, ref strError);
                }
            }

            return true;
        }

        /// <summary>
        /// 迁出
        /// </summary>
        /// <param name="flowId"></param>
        /// <returns></returns>
        public bool CheckOut(string flowId, ref string strError) {
            var flow = this.GetById(flowId);
            if (flow == null)
            {
                strError = "流程未找到，无法迁出！";
                return false;
            }
            if (flow.IsCheckOut)
            {
                strError = "流程已迁出，无法在次迁出！";
                return false;
            }
            flow.IsCheckOut = true;
            flow.CheckOutUserId = ApplicationEnvironments.DefaultSession.UserId;
            flow.CheckOutIp = ApplicationEnvironments.DefaultSession.IPAddress;
            FlowDesigner flowDesigner = null;
            if (!string.IsNullOrWhiteSpace(flow.Chart))
            {
                flowDesigner = JSONHelper.FromJson<FlowDesigner>(flow.Chart);
            }
            if (flowDesigner == null)
            {
                flowDesigner = new FlowDesigner();
            }
            flowDesigner.Flow = flow;
            CheckLogService checkLogService = new CheckLogService();
            var logEntity = checkLogService.Save(flow.FlowId, flow.FlowName, 0, ref strError);
            using (var tran = this.Begin())
            {
                try
                {
                    if (logEntity != null)
                    {
                        this.SaveOrUpdate<CheckLogEntity>(logEntity);
                    }
                    if (this.SaveOrUpdate<FlowEntity>(flow))
                    {
                        FileHelper.WriteLine(this.CheckoutPath + flow.FlowId + ".json", JSONHelper.ToJson(flowDesigner));
                    }
                    else
                    {
                        strError = "迁出异常";
                        return false;
                    }
                    this.Commit();
                }
                catch (Exception ex)
                {
                    this.Rollback();
                    throw ex;
                }
            }
            return true;
        }

        /// <summary>
        /// 迁入
        /// </summary>
        /// <param name="flowid"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool CheckIn(string flowid, ref string strError)
        {
            FlowDesigner designer = this.GetFlowById(flowid);
            if (designer == null)
            {
                strError = "流程未找到，无法迁出！";
                return false;
            }
            if (!designer.Flow.IsCheckOut)
            {
                strError = "流程尚未迁出，无需迁入！";
                return false;
            }
            if (!designer.Flow.CheckOutUserId.Equals(ApplicationEnvironments.DefaultSession.UserId))
            {
                strError = "流程不是由您迁出，无法操作！";
                return false;
            }
            if (this.Exist(designer.Flow.FlowName, designer.Flow.FlowId))
            {
                strError = "流程名称已存在，无法迁入！";
                return false;
            }
            if (!CheckFlow(designer, ref strError))
            {
                return false;
            }
            designer.Flow.IsCheckOut = false;
            designer.Flow.CheckOutUserId = ApplicationEnvironments.DefaultSession.UserId;
            designer.Flow.CheckOutIp = ApplicationEnvironments.DefaultSession.IPAddress;
            designer.Flow.Chart = JSONHelper.ToJson(designer);
            ICriterion criter = Expression.And(Expression.Eq(CheckLogEntity.__Status, 0), Expression.And(Expression.Eq(CheckLogEntity.__FlowId, flowid),
                     Expression.Eq(CheckLogEntity.__IsDeleted, false)));
            var logEntity = this.Select<CheckLogEntity>(criter);
          
            if (logEntity == null )
            {
                logEntity = new CheckLogEntity
                {
                    FlowId = flowid,
                    Status = 1,
                    CheckLogId=MyGenerateHelper.GenerateOrder(),
                    LastModifyDate = DateTime.Now,
                    ActionUserId = ApplicationEnvironments.DefaultSession.UserId,
                    LastModifyUserId = ApplicationEnvironments.DefaultSession.UserId,
                    FlowName = designer.Flow.FlowName

                };
            }
            using (var tran = this.Begin())
            {
                try
                {
                    if (this.SaveOrUpdate<FlowEntity>(designer.Flow))
                    {
                        if (logEntity != null)
                        {
                            logEntity.ActionUserId = ApplicationEnvironments.DefaultSession.UserId;
                            logEntity.Chart = designer.Flow.Chart;
                            logEntity.Status = 1;
                            this.SaveOrUpdate<CheckLogEntity>(logEntity);
                        }
                        FileHelper.Delete(this.CheckoutPath + designer.Flow.FlowId + ".json");

                    }
                    this.Commit();
                }
                catch (Exception ex)
                {
                    this.Rollback();
                    throw ex;
                }
            }

            return true;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isType"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool Delete(string id, int isType, ref string strError)
        {
            if (isType < 2)
            {
                var lst = this.Query<FlowTypeEntity>(Expression.And(Expression.Eq(FlowTypeEntity.__ParentId, id), Expression.Eq(FlowTypeEntity.__IsDeleted, false)));
                if (lst != null && lst.Count > 0)
                {
                    strError = "该类别下还有子类别，无法删除";
                    return false;
                }
                var lstFlow = this.Query<FlowEntity>(Expression.And(Expression.Eq(FlowEntity.__FlowTypeId, id), Expression.Eq(FlowTypeEntity.__IsDeleted, false)));
                if (lstFlow != null && lstFlow.Count > 0)
                {
                    strError = "该类别下还有流程，无法删除";
                    return false;
                }
                var lstTempFlow = GetTempAllFlow();
                if (lstTempFlow != null && lstTempFlow.Count > 0)
                {
                    var temp = lstTempFlow.Where(x => x.Flow.FlowTypeId.Equals(id) && !x.Flow.IsDeleted).FirstOrDefault();
                    if (temp != null)
                    {
                        strError = "该类别下还有流程，无法删除";
                        return false;
                    }
                }
                this.Delete<FlowTypeEntity>(id, true);
            }
            else if (isType == 2)
            {
                var designer = this.GetFlowById(id);
                if (designer != null)
                {
                    var lstQuery = this.Query<FlowVersionEntity>(Expression.And(Expression.Eq(FlowVersionEntity.__FlowId, id), Expression.Eq(FlowVersionEntity.__IsDeleted, false)));
                    if (lstQuery != null && lstQuery.Count > 0)
                    {
                        strError = "流程已发布子流程，无法删除";
                        return false;
                    }
                    if (designer.Flow.IsCheckOut && !designer.Flow.CheckOutUserId.Equals(ApplicationEnvironments.DefaultSession.UserId))
                    {
                        strError = "流程已迁出，无法删除";
                        return false;
                    }
                    this.Delete<FlowEntity>(id, true);
                    FileHelper.Delete(this.CheckoutPath + id + ".json");
                }
            }
            return true;
        }

        /// <summary>
        /// 获取编号
        /// </summary>
        /// <param name="flowId"></param>
        /// <param name="isType"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public string GetMaxNumber(string flowId, int isType, ref string strError)
        {
            var flowDesigner = this.GetFlowById(flowId);
            if (flowDesigner == null)
            {
                strError = "流程不存在，无法获取";
                return "";
            }
            if (flowDesigner.flowMax == null)
            {
                flowDesigner.flowMax = new FlowMaxNumber();
            }
            if (isType == 0)//节点
            {
                flowDesigner.flowMax.ActivityNum++;
                this.SaveFile(flowDesigner,ref strError);
                return flowDesigner.Flow.FlowId+ flowDesigner.flowMax.ActivityNum.ToString().PadLeft(3, '0');
            }
            else if (isType == 1)//参数
            {
                flowDesigner.flowMax.FlowParamNum++;
                this.SaveFile(flowDesigner, ref strError);
               return flowDesigner.Flow.FlowId + flowDesigner.flowMax.FlowParamNum.ToString().PadLeft(3, '0');
            }
            else if (isType == 2)//路径
            {
                flowDesigner.flowMax.PathNum++;
                this.SaveFile(flowDesigner, ref strError);
                return flowDesigner.Flow.FlowId +"P"+ flowDesigner.flowMax.PathNum.ToString().PadLeft(3, '0');
            }
            else if (isType == 3)//规则
            {
                flowDesigner.flowMax.FlowRuleNum++;
                this.SaveFile(flowDesigner, ref strError);
                return flowDesigner.Flow.FlowId + flowDesigner.flowMax.FlowRuleNum.ToString().PadLeft(3, '0');
            }
            return "";
        }


        #region 验证流程
        /// <summary>
        /// 验证流程
        /// </summary>
        /// <param name="flowDesigner"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool CheckWorkflow(string flowid, ref string strError)
        {
            FlowDesigner flowDesigner = this.GetFlowById(flowid);
            return CheckFlow(flowDesigner, ref strError);
        }

        /// <summary>
        /// 验证流程
        /// </summary>
        /// <param name="flowDesigner"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool CheckFlow(FlowDesigner flowDesigner, ref string strError)
        {
            List<string> lstError = new List<string>();
            if (flowDesigner == null)
            {
                strError = "流程未找到，无法验证";
                return false;
            }
            if (!VaildHelper.CheckVaild(flowDesigner.Flow, ref strError))
            {
                lstError.Add(strError);
            }
            if (flowDesigner.states == null || flowDesigner.states.Count <= 0
                || flowDesigner.activities == null || flowDesigner.activities.Count <= 0)
            {
                strError = "流程中没有节点";
                return false;
            }
            if (flowDesigner.activities.Count != flowDesigner.states.Count)
            {
                lstError.Add("流程中节点属性与图中节点不匹配");
            }
            if (flowDesigner.paths == null || flowDesigner.paths.Count <= 0)
            {
                lstError.Add("请设置流程流转路径");
            }
            foreach (var activity in flowDesigner.activities)
            {
                CheckActivity(flowDesigner, activity.Value, lstError);
            }
            if (flowDesigner.flowParams != null && flowDesigner.flowParams.Count > 0)
            {
                foreach (var flowParam in flowDesigner.flowParams)
                {
                    CheckParam(flowDesigner, flowParam.Value, lstError);
                }
            }
           
            if (flowDesigner.flowRules != null && flowDesigner.flowRules.Count > 0)
            {
                foreach (var flowRules in flowDesigner.flowRules)
                {
                    if ( flowRules.Value != null && flowRules.Value.Count > 0)
                    {
                        foreach (var flowrule in flowRules.Value)
                        {
                            CheckRules(flowDesigner, flowrule.Value, lstError);
                        }
                    }
                }
            }
            if (lstError != null && lstError.Count > 0)
            {
                foreach (var str in lstError)
                {
                    strError += "\r\n" + str;
                }
                return false;
            }

            return true;
        }

        /// <summary>
        /// 验证节点是否成功
        /// </summary>
        /// <param name="flowDesigner"></param>
        /// <param name="activityEntity"></param>
        /// <param name="lstError"></param>
        private bool CheckActivity(FlowDesigner flowDesigner, ActivityEntity activityEntity, List<string> lstError)
        {
            string strError = "";
            if (!VaildHelper.CheckVaild(activityEntity, ref strError))
            {
                lstError.Add(strError);
            }
            if (activityEntity.RecipientType < 20)
            {
                if (string.IsNullOrWhiteSpace(activityEntity.RecipientName) || string.IsNullOrWhiteSpace(activityEntity.RecipientId))
                {
                    lstError.Add(activityEntity.ActivityName + "节点接收人为空");
                }
            }
            var exist = flowDesigner.activities.Where(x => !x.Value.IsDeleted && x.Value.ActivityName.Equals(activityEntity.ActivityName) && x.Key != activityEntity.ActivityId).FirstOrDefault();
            if (!string.IsNullOrWhiteSpace(exist.Key))
            {
                lstError.Add(activityEntity.ActivityName + "已存在流程或者节点当中！");
            }
            return true;
        }

        /// <summary>
        /// 验证参数节点是否成功
        /// </summary>
        /// <param name="flowDesigner"></param>
        /// <param name="activityEntity"></param>
        /// <param name="lstError"></param>
        private bool CheckParam(FlowDesigner flowDesigner, FlowParamsEntity flowParams, List<string> lstError)
        {
            string strError = "";
            if (!VaildHelper.CheckVaild(flowParams, ref strError))
            {
                lstError.Add(strError);
            }
            var exist = flowDesigner.flowParams.Where(x => !x.Value.IsDeleted && x.Value.FlowParamName.Equals(flowParams.FlowParamName) && x.Key != flowParams.id).FirstOrDefault();
            if (!string.IsNullOrWhiteSpace(exist.Key))
            {
                lstError.Add(flowParams.FlowParamName + "已存在流程或者节点当中！");
            }
            return true;
        }
        /// <summary>
        /// 验证参数节点是否成功
        /// </summary>
        /// <param name="flowDesigner"></param>
        /// <param name="activityEntity"></param>
        /// <param name="lstError"></param>
        private bool CheckRules(FlowDesigner flowDesigner, FlowRulesEntity flowRules, List<string> lstError)
        {
            string strError = "";
            if (!VaildHelper.CheckVaild(flowRules, ref strError))
            {
                lstError.Add(strError);
            }

            if (flowDesigner.flowRules.ContainsKey(flowRules.ActivityId))
            {
                Dictionary<string, FlowRulesEntity> activityRule = flowDesigner.flowRules[flowRules.ActivityId];
                if (activityRule != null)
                {
                    var exist = activityRule.Where(y => y.Value.FlowRuleName.Equals(flowRules.FlowRuleName) && y.Key != flowRules.FlowRuleId).FirstOrDefault();
                    if (!string.IsNullOrWhiteSpace(exist.Key))
                    {

                        lstError.Add(flowRules.FlowRuleName + "规则名称已存在！");
                        return false;
                    }
                }
            }
            return true;
        }
        #endregion

        #region 发布流程
        /// <summary>
        /// 发布流程
        /// </summary>
        /// <param name="flowid"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public bool Publish(string flowid,string version, ref string strError, bool isCover = false)
        {
            if (!CheckWorkflow(flowid, ref strError))
            {
                return false;
            }
            FlowDesigner flowDesigner = this.GetFlowById(flowid);
           
            FlowVersionEntity versionEntity = null;
          
            ICriterion criterion = Expression.And(Expression.Eq(FlowVersionEntity.__IsDeleted, false),
            Expression.Eq(FlowVersionEntity.__FlowId, flowid));
            if (!string.IsNullOrWhiteSpace(version)&& version.ToInt()>0)
            {
                criterion = Expression.And(criterion,Expression.Eq(FlowVersionEntity.__Version, version));
            }
            versionEntity =this.Query<FlowVersionEntity>(criterion,Order.Desc(FlowVersionEntity.__Version)).FirstOrDefault();
            if (!isCover)
            {
                if (versionEntity != null)
                {
                    version = (versionEntity.Version + 1).ToString();
                }
                else
                {
                    version = "1";
                }
                versionEntity = new FlowVersionEntity
                {
                    FlowId = flowid,
                    FlowVersionId = flowid + version.PadLeft(3, '0'),
                    Version = version.ToInt(),
                    OrderNum = version.ToInt(),
                    ServiceClass= flowDesigner.Flow.ServiceClass,
                    Status = true,
                };
            }
            else {
                if (versionEntity == null)
                {
                    strError = "该版本不存在，无法覆盖！";
                    return false;
                }
               
            }
            versionEntity.OrderNum= versionEntity.Version= version.ToInt();
            if (flowDesigner.Flow.IsCheckOut)
            {
                strError = "流程已迁出，无法发布！";
                return false;
            }
            Dictionary<string, FlowDesignerPhase> lstStates = new Dictionary<string, FlowDesignerPhase>();
            foreach (var state in flowDesigner.states)
            {
                lstStates.Add(state.Key.Replace(versionEntity.FlowId, versionEntity.FlowVersionId), state.Value);
            }
            flowDesigner.states = lstStates;
            List<ActivityEntity> activities = new List<ActivityEntity>();
            Dictionary<string, ActivityEntity> flowActivities = new Dictionary<string, ActivityEntity>();
            foreach (var activity in flowDesigner.activities)
            {
                activity.Value.FlowId = versionEntity.FlowVersionId;
                activity.Value.ActivityId = activity.Value.ActivityId.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                activities.Add(activity.Value);
                flowActivities.Add(activity.Value.ActivityId, activity.Value);
            }
            flowDesigner.activities = flowActivities;
            List<FlowParamsEntity> flowParams = new List<FlowParamsEntity>();
            Dictionary<string, FlowParamsEntity> fParams = new Dictionary<string, FlowParamsEntity>();
            if (flowDesigner.flowParams != null && flowDesigner.flowParams.Count > 0)
            {
                foreach (var flowParam in flowDesigner.flowParams)
                {
                    flowParam.Value.FlowId = versionEntity.FlowVersionId;
                    flowParam.Value.FlowParamId = flowParam.Value.FlowParamId.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                    flowParams.Add(flowParam.Value);
                    fParams.Add(flowParam.Value.FlowParamId, flowParam.Value);
                }
            }
            flowDesigner.flowParams = fParams;
            List<FlowRulesEntity> lstflowRules = new List<FlowRulesEntity>();
            Dictionary<string, Dictionary<string, FlowRulesEntity>> fRules = new Dictionary<string, Dictionary<string, FlowRulesEntity>>();
            if (flowDesigner.flowRules != null && flowDesigner.flowRules.Count > 0)
            {
                foreach (var flowRules in flowDesigner.flowRules)
                {
                    Dictionary<string, FlowRulesEntity> fRuleEntity = new Dictionary<string, FlowRulesEntity>();
                    string key = flowRules.Key.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                    foreach (var flowrule in flowRules.Value)
                    {
                        flowrule.Value.FlowId = versionEntity.FlowVersionId;
                        flowrule.Value.FlowRuleId = flowrule.Value.FlowRuleId.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                        flowrule.Value.ActivityId = flowrule.Value.ActivityId.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                        flowrule.Value.ToActivity= flowrule.Value.ToActivity.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                        if (flowrule.Value.group != null)
                        {
                            flowrule.Value.Condition = flowrule.Value.group.ToJson();
                        }
                        lstflowRules.Add(flowrule.Value);
                        fRuleEntity.Add(flowrule.Value.FlowRuleId, flowrule.Value);
                    }
                    fRules.Add(key, fRuleEntity);
                }
            }
            flowDesigner.flowRules = fRules;
            Dictionary<string, FlowDesignerPhaseLink> pairs = new Dictionary<string, FlowDesignerPhaseLink>();
            foreach (var path in flowDesigner.paths)
            {
                path.Value.from = path.Value.from.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                path.Value.to = path.Value.to.Replace(versionEntity.FlowId, versionEntity.FlowVersionId);
                var newpath = new FlowRulesEntity
                {
                    FlowRuleId = path.Key.Replace(versionEntity.FlowId, versionEntity.FlowVersionId),
                    ActivityId = path.Value.from.Replace(versionEntity.FlowId, versionEntity.FlowVersionId),
                    ToActivity = path.Value.to.Replace(versionEntity.FlowId, versionEntity.FlowVersionId),
                    FlowId = versionEntity.FlowVersionId,
                    FlowRuleName = path.Value.lineType,
                    FlowRuleType = path.Value.lineType.ToLower().Equals("path") ? 0 : 1,
                    ToType = 0,
                    IsPath = true,
                    Condition = ""
                };
                lstflowRules.Add(newpath);
                pairs.Add(path.Key.Replace(versionEntity.FlowId, versionEntity.FlowVersionId), path.Value);
                //activity.Value.FlowId = versionEntity.FlowVersionId;
            }
         
            flowDesigner.paths = pairs;
            versionEntity.Chart = flowDesigner.ToJson();
            var  logEntity = new CheckLogEntity
            {
                FlowId = flowDesigner.Flow.FlowId,
                Status = 10,
                CheckLogId = Guid.NewGuid().ToString(),
                LastModifyDate = DateTime.Now,
                ActionUserId = ApplicationEnvironments.DefaultSession.UserId,
                LastModifyUserId = ApplicationEnvironments.DefaultSession.UserId,
                FlowName = flowDesigner.Flow.FlowName,
                Chart = versionEntity.Chart

          };
            flowDesigner.Flow.FlowId = versionEntity.FlowVersionId;
            flowDesigner.Flow.Version = versionEntity.Version.ToString();
            using (var tran = this.Begin())
            {
                try
                {
                    this.SaveOrUpdate<FlowVersionEntity>(versionEntity);
                    this.Delete<ActivityEntity>(Expression.Eq(ActivityEntity.__FlowId,versionEntity.FlowVersionId),false);
                    this.Delete<FlowParamsEntity>(Expression.Eq(FlowParamsEntity.__FlowId, versionEntity.FlowVersionId), false);
                    this.Delete<FlowRulesEntity>(Expression.Eq(FlowParamsEntity.__FlowId, versionEntity.FlowVersionId), false);
                    this.BatchSave<ActivityEntity>(activities);
                    this.BatchSave<FlowParamsEntity>(flowParams);
                    this.BatchSave<FlowRulesEntity>(lstflowRules);
                    this.SaveOrUpdate<CheckLogEntity>(logEntity);
                    this.Commit();
                }
                catch (Exception ex)
                {
                    this.Rollback();
                    throw ex;
                }
            }
                return true;
        }

         /// <summary>
        /// 撤销
        /// </summary>
        /// <param name="flowid">流程id</param>
        /// <param name="strError">错误信息</param>
        /// <returns></returns>
        public bool Revoke(string flowid, ref string strError)
        {
            FlowDesigner designer = this.GetFlowById(flowid);
            if (designer == null)
            {
                strError = "流程未找到，无法迁出！";
                return false;
            }
            if (!designer.Flow.IsCheckOut)
            {
                strError = "流程尚未迁出，无需迁入！";
                return false;
            }
            if (!designer.Flow.CheckOutUserId.Equals(ApplicationEnvironments.DefaultSession.UserId))
            {
                strError = "流程不是由您迁出，无法操作！";
                return false;
            }
           
            var flow=this.GetById<FlowEntity>(flowid);
            if(flow==null)
            {
                FileHelper.Delete(this.CheckoutPath + flowid + ".json");
                return true;             
            }
            flow.IsCheckOut = false;
            flow.CheckOutUserId = "";
            flow.CheckOutIp = "";
            designer.Flow.CheckOutUserId="";
             designer.Flow.CheckOutIp="";
              designer.Flow.IsCheckOut=false;
            ICriterion criter = Expression.And(Expression.Eq(CheckLogEntity.__Status, 0), Expression.And(Expression.Eq(CheckLogEntity.__FlowId, flowid),
                     Expression.Eq(CheckLogEntity.__IsDeleted, false)));
            var logEntity = this.Select<CheckLogEntity>(criter);
          
            if (logEntity == null )
            {
                logEntity = new CheckLogEntity
                {
                    FlowId = flowid,
                    Status = 2,
                    CheckLogId=MyGenerateHelper.GenerateOrder(),
                    LastModifyDate = DateTime.Now,
                    ActionUserId = ApplicationEnvironments.DefaultSession.UserId,
                    LastModifyUserId = ApplicationEnvironments.DefaultSession.UserId,
                    FlowName = designer.Flow.FlowName

                };
            }
            using (var tran = this.Begin())
            {
                try
                {
                    if (this.SaveOrUpdate<FlowEntity>(flow))
                    {
                        if (logEntity != null)
                        {
                            logEntity.ActionUserId = ApplicationEnvironments.DefaultSession.UserId;
                            logEntity.Chart = designer.ToJson();
                            logEntity.Status = 2;
                            this.SaveOrUpdate<CheckLogEntity>(logEntity);
                        }
                       

                    }
                    this.Commit();
                }
                catch (Exception ex)
                {
                    this.Rollback();
                    throw ex;
                }
            }
            FileHelper.Delete(this.CheckoutPath + designer.Flow.FlowId + ".json");
            return true;
        }
        #endregion
    }
}